﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace RAP.Framework.Libary.JSONSocket
{
  /// <summary>
  /// JSONSocket工具类
  /// </summary>
  public static class JSONSocketUtils
  {
    /// <summary>
    /// JSON协议的包头
    /// </summary>
    public static byte[] JSONPackegeHead = new byte[] { 0x55, 0xAA };

    /// <summary>
    /// 内容长度所占字节数
    /// </summary>
    public static byte ContentLengthBytes = 2;

    /// <summary>
    /// 将当前Socket按JSON数据传输协议进行处理
    /// </summary>
    /// <param name="socket"></param>
    /// <param name="onDataArrived"></param>
    /// <param name="onError"></param>
    public static void Receive(this Socket socket, Action<string> onDataArrived, Action<Exception> onError = null)
    {
      Func<bool> checkSocket = () => socket != null && socket.Connected;

      try
      {
        while (checkSocket())
        {
          //寻找包头
          var packegeHead = new byte[JSONPackegeHead.Length];
          if (!checkSocket())
          {
            return;
          }
          var receiveLength = socket.Receive(packegeHead);
          if (receiveLength != packegeHead.Length)
          {
            Thread.Sleep(1);
            continue;
          }
          //判断是否等于包头标识
          if (!CheckPackegeHead(packegeHead))
          {
            Thread.Sleep(1);
            continue;
          }
          if (!checkSocket())
          {
            return;
          }
          //获取内容长度
          var contentLen = new byte[ContentLengthBytes];
          receiveLength = socket.Receive(contentLen);
          if (receiveLength != contentLen.Length)
          {
            Thread.Sleep(1);
            continue;
          }
          var len = BitConverter.ToInt16(contentLen, 0);
          if (!checkSocket())
          {
            return;
          }
          //获取内容
          var content = new byte[len];
          receiveLength = socket.Receive(content);
          if (receiveLength != content.Length)
          {
            Thread.Sleep(1);
            continue;
          }
          var jsonData = Encoding.UTF8.GetString(content);
          onDataArrived?.Invoke(jsonData);
          Thread.Sleep(1);
        }
      }
      catch (Exception exc)
      {
        onError?.Invoke(exc);
      }

    }

    /// <summary>
    /// 按JSON协议发送数据
    /// </summary>
    /// <param name="socket"></param>
    /// <param name="jsonData"></param>
    public static void Send(this Socket socket, string jsonData)
    {
      var jsonBytes = Encoding.UTF8.GetBytes(jsonData);
      var sendData = new byte[JSONPackegeHead.Length + ContentLengthBytes + jsonBytes.Length];
      var dataLen = BitConverter.GetBytes((short)jsonBytes.Length);
      Array.Copy(JSONPackegeHead, 0, sendData, 0, 2);
      Array.Copy(dataLen, 0, sendData, 2, 2);
      Array.Copy(jsonBytes, 0, sendData, 4, jsonBytes.Length);
      socket.Send(sendData);
    }

    /// <summary>
    /// 检测包头是否正确
    /// </summary>
    /// <param name="packegeHead"></param>
    /// <returns></returns>
    public static bool CheckPackegeHead(byte[] packegeHead)
    {
      for (var i = 0; i < JSONPackegeHead.Length; i++)
      {
        if (JSONPackegeHead[i] != packegeHead[i])
        {
          return false;
        }
      }
      return true;
    }

  }
}
